#include "QRONode_P.h"

struct tempPropertyData{
    ObjectID id;
    int prop;
    QVariant value;
};
typedef QVector<tempPropertyData> PropDataList;

static PropDataList parsePropPacket(QRONode::Private* _P,QVariant value);
static void setPropertyToObject(QRONode::Private* _P,ObjectID remoteID,QList<QPair<int,QVariant>> propertys);
static void handlePropertyUpdate(QRONode::Private* _P,const PropDataList& dataMap);

void QRONode::Private::handlePropPacket(QVariant value)
{
    auto dataMap = parsePropPacket(this,value);
    handlePropertyUpdate(this,dataMap);
}

void QRONode::Private::onPushProperty(QObject* target,int prop,QVariant value)
{
    if(!m_objectIdMap.count(target)) return;
    auto localId = m_objectIdMap[target];
    auto remoteId = m_remoteIdMapper[localId];
    auto data = m_objectDataMap[localId];

    auto meta = data->obj->metaObject();
    auto roPropMeta = QRemoteObject2Meta::Instance()->findPropData(meta->className(),prop);
    if(roPropMeta.index == -1) return;
    if(roPropMeta.flag != QRemoteObject2::ROPropertyFlag::ReadWrite) return;

    //将属性值进行网络编码
    valueToNet(value);

    m_channel->pushProperty(remoteId,prop,value);
}

void QRONode::Private::onPropertyUpdate(QByteArray data)
{
    auto packet = uncompressVariant(data);
    handlePropPacket(packet);
}

static PropDataList parsePropPacket(QRONode::Private* _P,QVariant value)
{
    auto list = value.toList();
    PropDataList ret;

    for(const auto & i:list)
    {
        auto dataList = i.toList();
        ObjectID remoteId = dataList[0].value<ObjectID>();
        int prop = dataList[1].value<int>();
        QVariant value = dataList[2];

        ret << tempPropertyData{remoteId,prop,value};
    }


    return ret;
}

static void handlePropertyUpdate(QRONode::Private* _P,const PropDataList& dataMap)
{
    std::map<ObjectID,QList<QPair<int,QVariant>>> updateMap;
    for(const auto& i:dataMap)
    {
        auto remoteId = i.id;

        updateMap[remoteId].append(QPair<int,QVariant>(i.prop,i.value));
    }

    for(const auto &i:updateMap)
    {
        setPropertyToObject(_P,i.first,i.second);
    }
}

static void setPropertyToObject(QRONode::Private* _P,ObjectID remoteID,QList<QPair<int,QVariant>> propertys){

    QObject* target = NULL;

    auto localID = _P->m_remoteIdMapper.value(remoteID);
    auto localData = _P->m_objectDataMap.value(localID);
    if(!localData) return;
    target = localData->obj;

    if(!target) return;

    for(auto i:propertys)
    {
        auto metaProp = target->metaObject()->property(i.first);
        auto converted = i.second;
        _P->valueFromNet(converted,metaProp.typeId());
        metaProp.write(target,converted);
    }
}
